home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 526-550 / disk_528 / keymenu / src.lzh / KeyMenu-Handler.asm next >
Assembly Source File  |  1991-08-03  |  87KB  |  1,353 lines

  1. *******************************************************************************
  2. *
  3. * KeyMenu-Handler.asm  V1.05  21 Apr 1991
  4. *
  5. *
  6. *
  7. *   This program is loaded by 'KeyMenu' and stays resident in the 
  8. *   system until the user runs KeyMenu with the 'QUIT' option.
  9. *   
  10. *
  11. *
  12. * Modification History:
  13. *
  14. *       Date       By                       Modification
  15. *     --------  --------------------    --------------------------------------
  16. *     09/09/89  Ken Lowther             Initial release, V1.01
  17. *
  18. *     09/13/89  Ken Lowther             V1.02 - added qualifier keys to move
  19. *                                       mouse pointer to first/last item.
  20. *
  21. *     09/24/89  Ken Lowther             V1.02 - corrected positioning of mouse
  22. *                                       pointer on menus. The pointer was being
  23. *                                       positioned 1 pixel to the left. This
  24. *                                       really only mattered when the menu is
  25. *                                       1 pixel wide.
  26. *
  27. *     09/30/89  Ken Lowther             V1.02 - Keymenu no longer creates a 
  28. *                                       process for this module. Changed 'main'
  29. *                                       to set the DOS return code and return
  30. *                                       in case this module gets 'execute'ed.
  31. *
  32. *     10/03/89  Ken Lowther             V1.02 - Changed to ignore the 1st 
  33. *                                       occurance of a 'repeated' key. This
  34. *                                       is to fix a problem that occurs when
  35. *                                       there are more than 2 bitplanes in the
  36. *                                       screen.
  37. *
  38. *     03/02/91  Ken Lowther             V1.03 - Modified to use PointerPos 
  39. *                                       events rather than RawMouse events to
  40. *                                       position intuition's pointer. This 
  41. *                                       allows Keymenu to co-exist with most
  42. *                                       mouse accelerators.
  43. *
  44. *     03/02/91  Ken Lowther             V1.03 - Re-installed intuition pointer
  45. *                                       blanking option.
  46. *
  47. *     03/13/91  Ken Lowther             V1.04 - Corrected to ignore topedge
  48. *                                       values in menu definitions (as 
  49. *                                       intuition does).
  50. *
  51. *     04/13/91  Ken Lowther             V1.05 - Corrected problem with subitems
  52. *                                       that are rendered to the left of their
  53. *                                       associated menu item.
  54. *
  55. *     04/13/91  Ken Lowther             V1.05 - Implemented 2 stage activation
  56. *                                       sequence to allow intuition to get the
  57. *                                       menu active before positioning the
  58. *                                       pointer.
  59. *
  60. *     04/19/91  Ken Lowther             V1.05 - NEWPOINTERPOS events are now
  61. *                                       generated when running under release
  62. *                                       2.0.  This allows keymenu to work with
  63. *                                       all the new screen resolutions that 
  64. *                                       2.0 provides.
  65. *
  66. *******************************************************************************
  67.             nolist
  68.             include "macros.i"
  69.             include "exec/types.i"
  70.             include "exec/strings.i"
  71.             include "exec/nodes.i"
  72.             include "exec/ports.i"
  73.             include "exec/execbase.i"
  74.             include "exec/ables.i"
  75.             include "exec/interrupts.i"
  76.             include "exec/memory.i"
  77.             include "devices/inputevent.i"
  78.             include "intuition/intuition.i"
  79.             include "libraries/dos.i"
  80.             include "libraries/dosextens.i"
  81.             include "hardware/custom.i"
  82.             include "hardware/dmabits.i"
  83.             include "keymenu-handler.i"
  84.             list
  85.             nomlist
  86.             xdef    _dmaconr
  87.             xdef    _dmacon
  88.             xdef    _spr
  89.  
  90. *******************************************************************************
  91. *                                                                             *
  92. *   Displacements into Select routine.                                        *
  93. *                                                                             *
  94. *******************************************************************************
  95. s_top               equ                 si_top-si_jmp-2
  96. s_adjacent_top      equ                 si_adjacent_top-si_jmp-2
  97. s_adjacent_up       equ                 si_adjacent_up-si_jmp-2
  98. s_up                equ                 si_up-si_jmp-2
  99. s_adjacent_right    equ                 si_adjacent_right-si_jmp-2
  100. s_right             equ                 si_right-si_jmp-2
  101. s_leftmost          equ                 si_leftmost-si_jmp-2
  102. s_adjacent_down     equ                 si_adjacent_down-si_jmp-2
  103. s_bottom            equ                 si_bottom-si_jmp-2
  104. s_adjacent_left     equ                 si_adjacent_left-si_jmp-2
  105. s_down              equ                 si_down-si_jmp-2
  106. s_left              equ                 si_left-si_jmp-2
  107. s_rightmost         equ                 si_rightmost-si_jmp-2
  108.  
  109. gbl         equr    a4                  ; handler global area
  110.  
  111.             cseg
  112.             near    code
  113. *******************************************************************************
  114. *                                                                             * 
  115. *       main                                                                  *
  116. *                                                                             *
  117. *       This is the main routine of KeyMenu-Handler. It is where execution    *
  118. *       begins. Here we perform the following functions:                      *
  119. *           1) Initialize program. This consists of determining what task we  *
  120. *              are and finding the public message port that the KeyMenu       *
  121. *              program created for us. If the port doesn't exist or if        *
  122. *              another task already owns it, we just exit (this can happen if *
  123. *              the user somehow manages to run this program instead of        *
  124. *              KeyMenu). The global area behind the message port, created by  *
  125. *              Keymenu, is updated with our task address, the signal number   *
  126. *              to use to send messages to us and the address of our input     *
  127. *              handler routine. We then signal KeyMenu that we are            *
  128. *              initialized.                                                   *
  129. *           2) Wait for one of two events to occur. Either a message has been *
  130. *              directed to us via the public message port or KeyMenu has      *
  131. *              signalled us to stop. Process the event as appropriate.        *
  132. *           3) Step 2, above, is repeated until our 'active' flag is reset.   *
  133. *              This occurs when, at our request, the input_handler sends a    *
  134. *              message to us indicating it is ready to stop. We then cleanup  *
  135. *              any resources we have allocated and return to AmigaDOS.        *
  136. *                                                                             *
  137. *       Input Registers:                                                      *
  138. *           None.                                                             *
  139. *                                                                             *
  140. *       Output Registers:                                                     *
  141. *           None.                                                             *
  142. *                                                                             *
  143. *******************************************************************************
  144. main        movem.l mainregs,-(sp)          ; save entry registers
  145. *-----------------------------------------------------------------------------*
  146. *           do initialization                                                 *
  147. *-----------------------------------------------------------------------------*
  148.             move.l  AbsExecBase,a6          ; setup base for exec.library
  149.             sub.l   a1,a1                   ; set to find our task
  150.             Call    FindTask                ; get pointer to our task
  151.             move.l  d0,a2                   ; get task address
  152.             clr.l   pr_ConsoleTask(a2)      ; clear console handler pointer
  153.             lea     myport(pc),a1           ; pointer to port name
  154.             Call    FindPort                ; go find our port
  155.             tst.l   d0                      ; does it exist ?
  156.             beq     main060                 ; no, must have it, get out
  157.             move.l  d0,gbl                  ; save pointer to our world
  158.             tst.l   MP_SIGTASK(gbl)         ; is a task already there ?
  159.             bne     main060                 ; yes, branch
  160. *-----------------------------------------------------------------------------*
  161. *           everything seems ok, update our global area and signal KeyMenu to *
  162. *           go ahead and add our input_handler routine to the input.device    *
  163. *-----------------------------------------------------------------------------*
  164.             moveq.l #-1,d0                   
  165.             Call    AllocSignal             ; get a signal for our task
  166.             move.b  d0,MP_SIGBIT(gbl)       ; save the signal number
  167.             move.l  a2,MP_SIGTASK(gbl)      ; make our task the one to signal
  168.             move.l  a2,gb_handtask(gbl)
  169.             lea     input_handler(pc),a1    ; get addr of input handler code
  170.             move.l  a1,gb_handler+IS_CODE(gbl) ; put it in interrupt struct
  171.             jsr     dosignal                ; go signal companion task
  172.             moveq.l #1,d4                   ; set active flag
  173. *-----------------------------------------------------------------------------*
  174. *           if we are still active, wait for something to happen              *
  175. *-----------------------------------------------------------------------------*
  176. main010     tst.w   d4                      ; are we still active ?
  177.             beq     main050                 ; no, go clean things up
  178.             clr.l   d1                      ; clear work register
  179.             move.b  MP_SIGBIT(gbl),d1       ; get signal bit number
  180.             bset.l  d1,d0                   ; create signal mask
  181.             bset.l  #SIGBREAKB_CTRL_C,d0    ; set break bit
  182.             Call    Wait                    ; wait for something to happen
  183. *-----------------------------------------------------------------------------*
  184. *           An event occurred! Determine if KeyMenu signalled 'CTRL C'        *
  185. *           telling us to stop. If not, there must be a message waiting on    *
  186. *           the message port.                                                 *
  187. *-----------------------------------------------------------------------------*
  188.             btst.l  #SIGBREAKB_CTRL_C,d0    ; did user request us to stop ?
  189.             beq     main015                 ; no, branch
  190.             bset.b  #FLAGB_Stop_requested,gb_flags(gbl) ; set stop requested
  191.                                             ; this tells the input handler to 
  192.                                             ; stop the next time it is entered
  193.             bra     main010                 ; go wait for input handler to stop
  194. *-----------------------------------------------------------------------------*
  195. *           get a message from the message port and determine what it is      *
  196. *-----------------------------------------------------------------------------*
  197. main015     move.l  gbl,a0                  ; get address of message port
  198.             Call    GetMsg                  ; get any message placed there
  199.             tst.l   d0                      ; was there a message queued ?
  200.             beq     main010                 ; no, branch
  201.             move.l  d0,a2                   ; save message address
  202.             cmp.w   #req_stopped,LN_NAME(a2) ; stop message ?
  203.             bne     main020                 ; no, branch
  204. *-----------------------------------------------------------------------------*
  205. *           A 'stop' message was received from the input handler. Clear our   *
  206. *           'active' flag.                                                    *
  207. *-----------------------------------------------------------------------------*
  208.             clr.l   d4                      ; yes, clear active flag
  209. main020     cmp.w   #req_onsprite,LN_NAME(a2) ; request to turn sprites on ?
  210.             bne     main030                 ; no, branch
  211. *-----------------------------------------------------------------------------*
  212. *           A 'onsprite' request was received from the input handler.         *
  213. *           This causes us to turn sprites back on so the user can see        *
  214. *           the pointer again (if we turned them off in the first place)      *
  215. *-----------------------------------------------------------------------------*
  216.             btst.b  #FLAGB_Blanked,gb_flags2(gbl) ; did we turn sprites off ?
  217.             beq     main040                      ; no, don't turn them on
  218.             far     data
  219.             move.w  #DMAF_SPRITE+DMAF_SETCLR,_dmacon ; sprites on
  220.             near    data
  221.             bra     main040
  222. main030     cmp.w   #req_offsprite,LN_NAME(a2) ; request to turn sprites off ?
  223.             bne     main040                    ; no, branch
  224. *-----------------------------------------------------------------------------*
  225. *           An 'offsprite' request was received from the input handler. This  *
  226. *           causes us to turn off sprites to remove the pointer from the      *
  227. *           view during menu operations.  If sprites are already turned off,  *
  228. *           we do nothing.                                                    *
  229. *-----------------------------------------------------------------------------*
  230.             bclr.b  #FLAGB_Blanked,gb_flags2(gbl)
  231.             far     data
  232.             btst.b  #DMAB_SPRITE,_dmaconr+1 ; are sprites on ?
  233.             near    data
  234.             beq     main040                 ; no, branch
  235.             Call    WaitTOF,gb_IBase(gbl)   ; wait for the proper time
  236.             far     data
  237.             move.w  #DMAF_SPRITE,_dmacon    ; turn sprites off
  238.             clr.w   _spr+sd_dataa
  239.             clr.w   _spr+sd_dataB
  240.             near    data
  241.             bset.b  #FLAGB_Blanked,gb_flags2(gbl) ; remember we turned sprites off
  242. *-----------------------------------------------------------------------------*
  243. *           free the message we received and loop to see if there is more     * 
  244. *-----------------------------------------------------------------------------*
  245. main040     clr.l   d0
  246.             move.l  a2,a1                   ; setup addr of block to free
  247.             move.w  MN_LENGTH(a1),d0        ; setup length of block to free
  248.             Call    FreeMem                 ; go free it
  249.             bra     main015                 ; loop for next message
  250.  
  251. myport      portname
  252.             
  253. *-----------------------------------------------------------------------------*
  254. *           We are no longer active, cleanup after ourselves and get out      *
  255. *-----------------------------------------------------------------------------*
  256. main050     move.l  gbl,a0                  ; get address of message port
  257.             Call    GetMsg                  ; get any message placed there
  258.             tst.l   d0                      ; was there a message queued ?
  259.             beq     main055                 ; no, branch
  260.             move.l  d0,a1                   ; setup to free the block
  261.             clr.l   d0
  262.             move.w  MN_LENGTH(a1),d0        ; setup length of block to free
  263.             Call    FreeMem                 ; go free it
  264.             bra     main050                 ; loop for next message
  265. main055     clr.l   d0
  266.             move.b  MP_SIGBIT(gbl),d0       ; get signal number
  267.             Call    FreeSignal              ; go free it
  268.             Forbid
  269.             jsr     dosignal                ; go signal companion task
  270. main060     movem.l (sp)+,mainregs          ; restore entry registers
  271.             rts                             ; return to AmigaDOS
  272. mainregs    reg     d1-d7/a0-a6
  273.  
  274.  
  275. *******************************************************************************
  276. *                                                                             * 
  277. *       dosignal                                                              *
  278. *                                                                             *
  279. *       Send a signal to our companion task (should be KeyMenu).              *
  280. *                                                                             *
  281. *       Input Registers:                                                      *
  282. *           a4 - global work area                                             *
  283. *                                                                             *
  284. *       Output Registers:                                                     *
  285. *           None.                                                             *
  286. *                                                                             *
  287. *******************************************************************************
  288. dosignal    clr.l   d1                      ; clear work register
  289.             move.b  gb_tasksignum(gbl),d1   ; get keymenu task signal number
  290.             bset.l  d1,d0                   ; create signal mask
  291.             move.l  gb_task(gbl),a1         ; get task to signal
  292.             Call    Signal                  ; signal the task that we are ready
  293.             rts
  294.  
  295. ******************************************************************************
  296. *                                                                             * 
  297. *       input_handler                                                         *
  298. *                                                                             *
  299. *       This routine is added to the input.device's list of handlers by the   *
  300. *       KeyMenu program. It is called whenever an input event, such as a      *
  301. *       keyboard press or mouse movement, occurs. In general, the input event *
  302. *       chain is scanned to see if the user has pressed any one of the        *
  303. *       various keys that we care about. If so, the input event representing  *
  304. *       that keypress is replaced with a mouse event(s) to accomplish         *
  305. *       KeyMenu's purpose. Note that the memory associated with event(s) that *
  306. *       are removed from the list actually belongs to the creator of that     *
  307. *       event. It is the event creator's responsibility to free this memory.  *
  308. *       See the RKM for more info about input handlers and the input.device   *
  309. *                                                                             *
  310. *       Input Registers:                                                      *
  311. *           a0 - input event chain, a forward reference linked list with the  *
  312. *                last event in the chain containing a 'NULL' reference.       *
  313. *           a1 - global work area                                             *
  314. *                                                                             *
  315. *       Output Registers:                                                     *
  316. *           d0 - new input event chain                                        *
  317. *                                                                             *
  318. *******************************************************************************
  319. input_handler
  320.  
  321. laste       equr    a1                      ; last event handled in chain
  322. ev          equr    a2                      ; original event passed to us
  323. ep          equr    a3                      ; current event pointer
  324.  
  325.             movem.l ihregs,-(sp)            ; save registers
  326.             move.l  a1,gbl                  ; setup pointer to our world
  327.             move.l  a0,ev                   ; save pointer to input event chain
  328. *-----------------------------------------------------------------------------*
  329. *           If 'stop' has been posted, check to see if there is currently a   *
  330. *           menu active. If so, wait for the user to get out of it otherwise  *
  331. *           send a 'stop' message (actually means 'ready to stop') to the     *
  332. *           KeyMenu-Handler process.                                          *
  333. *-----------------------------------------------------------------------------*
  334.             btst.b  #FLAGB_Stop_requested,gb_flags(gbl) ; stop requested ?
  335.             beq     ih010                   ; no, branch
  336.             btst.b  #FLAGB_MActive,gb_flags(gbl) ; is a menu currently active ?
  337.             bne     ih010                        ; yes, branch
  338.             btst.b  #FLAGB_Stopped,gb_flags(gbl) ; stop already been posted ?
  339.             bne     ih010                        ; yes, branch
  340.             moveq.l #req_stopped,d0         ; set type of request to send
  341.             jsr     sendrequest             ; go send it
  342.             bset.b  #FLAGB_Stopped,gb_flags(gbl) ; indicate stop has been posted
  343. *-----------------------------------------------------------------------------*
  344. *           Begin stepping through the input event chain                      *
  345. *-----------------------------------------------------------------------------*
  346. ih010       FORBID                          ; don't let anyone mess with events
  347.             sub.l   laste,laste             ; clear last event register
  348.             move.l  ev,ep                   ; setup event work register
  349.             bclr.b  #FLAGB_Events_inserted,gb_flags(gbl) ; clear inserted flag
  350.             bra     ih040                   ; go see if an event exists
  351. ih015       btst.b  #FLAGB_MActive,gb_flags(gbl) ; is a menu currently active ?
  352.             beq     ih017                        ; no, branch
  353.             btst.b  #FLAGB_ASC,gb_flags2(gbl) ; is activation sequence complete ?
  354.             bne     ih017                    ; yes, branch
  355.             jsr     Check_Menu_Active       ; go see if the menu is active yet 
  356.             bra     ih045                   ; get out until menu is active 
  357. ih017       cmp.b   #IECLASS_RAWKEY,ie_Class(ep) ; Raw key event ?
  358.             bne     ih025                   ; no, branch
  359. *-----------------------------------------------------------------------------*
  360. *           This is a RAWKEY event (keypress/keyrelease).                     *
  361. *-----------------------------------------------------------------------------*
  362.             jsr     Check_RawKey_Event      ; go look at this one
  363.             beq     ih030                   ; do we keep it ? yes, branch
  364.             move.l  laste,d0                ; was there a previous event ?
  365.             bne     ih020                   ; yes, branch
  366.             move.l  ie_NextEvent(ep),ev     ; drop the event
  367.             bra     ih035                     
  368. ih020       move.l  ie_NextEvent(ep),ie_NextEvent(laste)
  369.             bra     ih035                   ; loop
  370. *-----------------------------------------------------------------------------*
  371. *           Here we look for a 'MENUDOWN' event. If this occurs while we have *
  372. *           a menu active, it indicates that the user pressed the right mouse *
  373. *           button intending to take over menu selection with the mouse.      *
  374. *-----------------------------------------------------------------------------*
  375. ih025       cmp.b   #IECLASS_RAWMOUSE,ie_Class(ep) ; is this a raw mouse event ?
  376.             bne     ih030                   ; no, branch
  377.             cmp.w   #MENUDOWN,ie_Code(ep)   ; is it a menu down event ?
  378.             bne     ih030                   ; no, branch
  379.             btst.b  #FLAGB_MActive,gb_flags(gbl) ; is a menu in progress ?
  380.             beq     ih030                   ; no, branch
  381.             bclr.b  #FLAGB_MActive,gb_flags(gbl) ; give control of menu to mouse
  382.             moveq.l #req_onsprite,d0
  383.             jsr     sendrequest             ; go reset intuition pointer
  384. *-----------------------------------------------------------------------------*
  385. *           Now we look to see if we inserted any events in the chain. If so, *
  386. *           we must get out. This is because we only have a fixed number of   *
  387. *           input event areas allocated (3) and they can be used only once    *
  388. *           per invocation of the handler. This could be a potential problem  *
  389. *           in that we could miss events that we care about (since we don't   *
  390. *           look at the remaining events in the event chain). However, this   *
  391. *           is nothing that would cause harm to the system. It would just     *
  392. *           appear to the user as though a keypress intended to cause a menu  *
  393. *           operation didn't take. This is better than incuring the overhead  *
  394. *           and buffer management problems associated with dynamically        *
  395. *           allocating input events.                                          *
  396. *-----------------------------------------------------------------------------*
  397. ih030       move.l  ep,laste                ; save this event
  398. ih035       btst.b  #FLAGB_Events_inserted,gb_flags(gbl) ; were events inserted?
  399.             bne     ih045                   ; yes, branch
  400. *-----------------------------------------------------------------------------*
  401. *           Setup to process the next event if one exists, otherwise get out  *
  402. *-----------------------------------------------------------------------------*
  403.             move.l  ie_NextEvent(ep),ep     ; get next event
  404. ih040       move.l  ep,d0                   ; set cc
  405.             bne     ih015                   ; go check it
  406. ih045       PERMIT
  407.             move.l  ev,d0                   ; pass event on
  408.             movem.l (sp)+,ihregs            ; restore registers
  409.             rts                             ; return to input device
  410. ihregs      reg     a0/a1/a2/a3/a4/a6
  411.  
  412. *******************************************************************************
  413. *                                                                             * 
  414. *       sendrequest                                                           *
  415. *                                                                             *
  416. *       This routine is called by the input handler when it wishes to send a  *
  417. *       request message to the KeyMenu-Handler process. There are currently   *
  418. *       three kinds of messages that may be sent:                             *
  419. *           1)  req_offsprite, to blank the intuition pointer during menu     *
  420. *               operations.                                                   *
  421. *           2)  req_onsprite, to restore the intuition pointer when menu      *
  422. *               operations are finished.                                      *
  423. *           3)  req_stopped, to signal that the handler is ready to stop.     *
  424. *       Sendrequest is always called regardless of the setting of the hide    *
  425. *       intuition pointer option. This is where we determine whether or not   *
  426. *       to actually send the request.                                         *
  427. *                                                                             *
  428. *       Input Registers:                                                      *
  429. *           d0 - type of request to be sent                                   *
  430. *           a4 - global work area                                             *
  431. *                                                                             *
  432. *       Output Registers:                                                     *
  433. *           none.                                                             *
  434. *                                                                             *
  435. *******************************************************************************
  436. sendrequest movem.l sendreqregs,-(sp)       ; save entry registers
  437.             btst.b  #FLAGB_Blank_pointer,gb_flags(gbl) ; blank pointer option on ?
  438.             bne     sendreq010              ; yes, branch
  439.             cmp.w   #req_stopped,d0         ; is this a 'stopped' request ?
  440.             bne     sendreq020              ; no, branch
  441. sendreq010  move.l  d0,d2                   ; save request type
  442.             move.l  #MEMF_CLEAR+MEMF_PUBLIC,d1 ; set attributes
  443.             move.l  #MN_SIZE,d0             ; set size of block
  444.             Call    AllocMem                ; go allocate a block
  445.             tst.l   d0                      ; was a block given to us ?
  446.             beq     sendreq020              ; no, branch
  447.             move.l  d0,a1                   ; yes, save pointer to block
  448.             move.w  d2,LN_NAME(a1)          ; format message
  449.             clr.l   MN_REPLYPORT(a1)
  450.             move.w  #MN_SIZE,MN_LENGTH(a1)
  451.             move.l  gbl,a0
  452.             Call    PutMsg                  ; write it to the port
  453. sendreq020  movem.l (sp)+,sendreqregs       ; restore registers
  454.             rts                             ; return to caller
  455. sendreqregs reg     a0/a1/d0-d2
  456.  
  457. *******************************************************************************
  458. *                                                                             * 
  459. *       Check_Menu_Active                                                     *
  460. *                                                                             *
  461. *       This routine checks the active window to see if the menu has been     *
  462. *       activated yet.  If so, we finish our activation sequence by           *
  463. *       positioning the pointer on the desired menuitem. Otherwise we wait    *
  464. *       for intuition to get around to activating the menu.                   *
  465. *                                                                             *
  466. *       Input Registers:                                                      *
  467. *           a4 - global work area                                             *
  468. *                                                                             *
  469. *       Output Registers:                                                     *
  470. *           none                                                              *
  471. *                                                                             *
  472. *******************************************************************************
  473. Check_Menu_Active
  474.             movem.l cmaregs,-(sp)           ; save registers
  475.             move.l  gb_window(gbl),a1       ; get pointer to the window
  476.             move.l  gb_IBase(gbl),a2        ; get intuitionbase
  477.             cmp.l   ib_ActiveWindow(a2),a1  ; is same window active ?
  478.             beq     cma005                  ; yes, branch
  479. cma003      bclr.b  #FLAGB_MActive,gb_flags(gbl) ; clear our activation flag
  480.             moveq.l #req_onsprite,d0
  481.             jsr     sendrequest             ; go reset intuition pointer
  482.             bra     cma010
  483. cma005      move.l  wd_Flags(a1),d0         ; get window's flags
  484.             btst.l  #MENUSTATE_B,d0         ; is the menu active ?
  485.             bne     cma007                  ; yes, branch
  486.             move.b  gb_waitcnt(gbl),d0      ; no, get wait counter
  487.             add.b   #1,d0                   ; bump counter
  488.             move.b  d0,gb_waitcnt(gbl)      ; save the counter
  489.             beq     cma003                  ; if we wrap to zero, reset
  490.             bra     cma010                  ; wait somemore
  491. cma007      moveq.l #2,d0                   ; indicate 2 events to be built
  492.             jsr     dobuild                 ; go build the necessary events
  493.             bset.b  #FLAGB_ASC,gb_flags2(gbl) ; indicate activation complete
  494. cma010      movem.l (sp)+,cmaregs           ; restore registers
  495.             rts                             ; return to caller
  496. cmaregs     reg     a0-a2
  497.  
  498. *******************************************************************************
  499. *                                                                             * 
  500. *       Check_RawKey_Event                                                    *
  501. *                                                                             *
  502. *       This routine checks each RAWKEY event (keypress/keyrelease) to see if *
  503. *       it is one that we are interested in. If it is, the event that is      *
  504. *       passed to us is replaced with events to do the appropriate KeyMenu    *
  505. *       function. Events that have no meaning for us are passed back to the   *
  506. *       caller indicating that they should remain in the input event chain.   *
  507. *                                                                             *
  508. *       Input Registers:                                                      *
  509. *           a3 - rawkey event to be checked                                   *
  510. *           a4 - global work area                                             *
  511. *                                                                             *
  512. *       Output Registers:                                                     *
  513. *           d0 - 0=discard the event, 1=keep the event                        *
  514. *                                                                             *
  515. *******************************************************************************
  516. Check_RawKey_Event
  517.             movem.l creregs,-(sp)           ; save registers
  518.             clr.l   d0
  519.             btst.b  #IEQUALIFIER_REPEAT_R,ie_Qualifier(a3)  ; is it a repeat ?
  520.             beq     cre003                  ; no, branch
  521.             btst.b  #FLAGB_Repeat_skipped,gb_flags(gbl) ; have we skipped one ?
  522.             bne     cre004                  ; yes, branch
  523.             bset.b  #FLAGB_Repeat_skipped,gb_flags(gbl) ; indicate repeat skipped
  524.             bra     cre_remove              ; remove it from the input chain
  525. cre003      bclr.b  #FLAGB_Repeat_skipped,gb_flags(gbl) ; clear repeat skipped
  526. cre004      btst.b  #FLAGB_MActive,gb_flags(gbl) ; is a menu currently active ?
  527.             bne     cre035                  ; yes, branch
  528. *-----------------------------------------------------------------------------*
  529. *           A menu is not currently active, check to see if one is being      *
  530. *           activated (keypress of the configured activation key).            *
  531. *-----------------------------------------------------------------------------*
  532.             move.b  gb_AKey(gbl),d0         ; get configured activation key code
  533.             cmp.w   ie_Code(a3),d0          ; Menu Activate Key ?
  534.             bne     cre010                  ; no, branch
  535. *-----------------------------------------------------------------------------*
  536. *           The user pressed the menu activation key, set a flag indicating   *
  537. *           that fact and wait to see if the key is released without pressing *
  538. *           any other keys.                                                   *
  539. *-----------------------------------------------------------------------------*
  540.             bset.b  #FLAGB_AKey_down,gb_flags(gbl) ; indicate Menu activate key
  541.                                                    ; down
  542. cre005      bra     cre_remove              ; remove this event
  543. cre010      bset.l  #IECODE_UP_PREFIX_R,d0  ; form keyrelease keycode
  544.             cmp.w   ie_Code(a3),d0          ; is it activate menu keyrelease ?
  545.             beq     cre014                  ; yes, branch
  546. cre012      bclr.b  #FLAGB_AKey_down,gb_flags(gbl) ; clear activate key down
  547.             bra     cre_keep                ; keep this event
  548. cre014      btst.b  #FLAGB_AKey_down,gb_flags(gbl) ; is activate key down still
  549.                                                    ; posted ?
  550.             beq     cre012                  ; no, branch
  551. *-----------------------------------------------------------------------------*
  552. *           The user pressed and released the menu activation key without     *
  553. *           hitting any other keys, find the current window and see if it has *
  554. *           a menu.                                                           *
  555. *-----------------------------------------------------------------------------*
  556.             move.l  gb_IBase(gbl),a5        ; get intuitionbase
  557.             move.l  ib_ActiveWindow(a5),d0  ; get current window
  558.             beq     cre005                  ; if none, branch
  559.             move.l  d0,a1                   ; save pointer to current window
  560.             move.l  wd_MenuStrip(a1),d0     ; get window's menu
  561.             beq     cre005                  ; if none, branch
  562.             move.l  d0,a0                   ; save menu for use later
  563.             move.l  wd_Flags(a1),d0         ; get window's flags
  564.             btst.l  #MENUSTATE_B,d0         ; is a menu already active ?
  565.             bne     cre005                  ; yes, branch
  566. *-----------------------------------------------------------------------------*
  567. *           The current window has a menu, check the RMBTRAP flag. If this is *
  568. *           set and the user didn't specify that we can clear it, then we     *
  569. *           can't use this menu.                                              *
  570. *-----------------------------------------------------------------------------*
  571.             btst.l  #RMBTRAP_B,d0           ; is RMBTRAP set in window ?
  572.             beq     cre015                  ; no, branch
  573.             btst.b  #FLAGB_Clear_rmbtrap,gb_flags(gbl) ; clear rmbtrap option 
  574.                                                        ; set ?
  575.             beq     cre005                  ; no, ignore the menu
  576.             bclr.l  #RMBTRAP_B,d0           ; clear RMBTRAP bit
  577.             move.l  d0,wd_Flags(a1)         ; update window's flags
  578. *-----------------------------------------------------------------------------*
  579. *           Finally, a menu we can use. Update our globals.                   *
  580. *-----------------------------------------------------------------------------*
  581. cre015      move.l  a0,gb_menu(gbl)         ; update our Menu pointer
  582.             move.l  a1,gb_window(gbl)       ; update our window pointer
  583. *-----------------------------------------------------------------------------*
  584. *           Now look to see if the menu and menu item saved in our globals is *
  585. *           still valid for this menu. If so, we will position the mouse on   *
  586. *           them otherwise we'll put the mouse on the topmost item in the     *
  587. *           leftmost menu.                                                    *
  588. *-----------------------------------------------------------------------------*
  589.             move.l  gb_currentmenu(gbl),a1  ; get saved menu
  590.             jsr     Verify_Item             ; go verify currentmenu
  591.             bne     cre020                  ; does it exist ? yes, use it
  592.             move.w  #s_leftmost,d0          ; no, setup to find leftmost menu
  593.             jsr     Select_Item             ; go select a Menu
  594.             move.l  d0,gb_currentmenu(gbl)  ; update our globals with new menu
  595. cre020      move.l  gb_currentmenu(gbl),a0  ; get current menu
  596.             move.l  mu_FirstItem(a0),a0     ; point to first menu item
  597.             move.l  gb_currentitem(gbl),a1  ; get current menu item
  598.             jsr     Verify_Item             ; go verify current item
  599.             bne     cre025                  ; does it exist ? yes, branch
  600.             move.w  #s_top,d0               ; no, setup to find top menuitem
  601.             jsr     Select_Item             ; go select menu item
  602.             move.l  d0,gb_currentitem(gbl)  ; update our globals
  603. *-----------------------------------------------------------------------------*
  604. *           Save the current mouse position so we can put it back where we    *
  605. *           found it when we're done. set/clear various flags reflecting our  *
  606. *           current state. One event is inserted in the event chain.          *
  607. *           A rawmouse menudown event that causes intuition to activate the   *
  608. *           menu. The second stage of the activation sequence will position   * 
  609. *           the pointer on the desired menu item (see Check_Active_Menu)      *
  610. *-----------------------------------------------------------------------------*
  611. cre025      move.w  ib_MouseX(a5),gb_old_MouseX(gbl) ; save current X
  612.             move.w  ib_MouseY(a5),gb_old_MouseY(gbl) ; save current Y
  613.             btst.b  #FLAGB_Release2,gb_flags2(gbl)   ; release 2 ?
  614.             beq     cre026                           ; no, branch
  615.             move.l  gb_window(gbl),a5       ; get current window
  616.             move.l  wd_WScreen(a5),a5       ; get window's screen
  617.             move.w  sc_MouseX(a5),gb_old_MouseX(gbl) ; save current X
  618.             move.w  sc_MouseY(a5),gb_old_MouseY(gbl) ; save curreny Y
  619. cre026      clr.l   gb_currentsubitem(gbl)  ; no subitem at present
  620.             move.w  #MENUDOWN,d0            ; setup to insert a menudown event
  621.             move.l  a3,a1                   ; event to attach new event to
  622.             jsr     Insert_RawMouse_Event   ; go insert the rawmouse event
  623.             bclr.b  #FLAGB_AKey_down,gb_flags(gbl) ; no longer waiting for
  624.                                                    ; activate key down event
  625.             clr.b   gb_waitcnt(gbl)         ; clear wait counter
  626.             bclr.b  #FLAGB_ASC,gb_flags2(gbl) ; indicate activation in progress
  627.             move.l  #req_offsprite,d0         ; setup to send request
  628. cre027      bchg.b  #FLAGB_MActive,gb_flags(gbl) ; invert menu active bit
  629.             jsr     sendrequest             ; send pointer req to our task
  630.             bra     cre_remove              ; go to common return
  631. *-----------------------------------------------------------------------------*
  632. *           A menu is currently active, check for the various keys that we    *
  633. *           care about.                                                       *
  634. *-----------------------------------------------------------------------------*
  635. cre035      move.b  gb_DKey(gbl),d0
  636.             cmp.w   ie_Code(a3),d0          ; Deactivate key ?
  637.             bne     cre040                  ; no, branch
  638. *-----------------------------------------------------------------------------*
  639. *           The menu 'deactivate' key was pressed. Three events are inserted  *
  640. *           in the event chain. They consist of a pointerpos event to         *
  641. *           position the pointer in the menu strip followed by a rawmouse     *
  642. *           menuup event that causes intuition to deactivate the menu without *
  643. *           selecting anything followed by another pointerpos event to put    *
  644. *           the pointer back where we found it when the menu was activated.   *
  645. *-----------------------------------------------------------------------------*
  646.             moveq.l #3,d0                   ; build 2 events
  647.             jsr     dobuild                 ; go build mouse event(s)
  648.             move.w  #MENUUP,d0              ; setup for a menu up rawmouse event
  649.             move.l  a0,a1                   ; event to attach new event to
  650.             jsr     Insert_RawMouse_Event   ; go insert the a rawmouse event
  651.             move.l  #req_onsprite,d0        ; setup to restore pointer
  652.             bra     cre027                  ; get out
  653.  
  654. cre040      move.b  gb_SKey(gbl),d0
  655.             cmp.w   ie_Code(a3),d0          ; Select Key ?
  656.             bne     cre055                  ; yes, branch
  657. *-----------------------------------------------------------------------------*
  658. *           The menu 'select' key was pressed. Two events are inserted in the *
  659. *           event chain. They consist of a menuup rawmouse event to select    *
  660. *           the current menu item, followed by a pointer event to put the     *
  661. *           pointer back where we found it when the menu was activated.       *
  662. *-----------------------------------------------------------------------------*
  663.             move.l  a3,a1                   ; event to attach new ones to
  664.             move.w  #MENUUP,d0              ; set type of rawmouse event
  665.             jsr     Insert_RawMouse_Event   ; go insert a menuup event
  666.             move.w  gb_old_MouseX(gbl),d0   ; get saved mouse x coordinate
  667.             move.w  gb_old_MouseY(gbl),d1   ; get saved mouse y cooridnate
  668.             move.l  a0,a1                   ; event to attach new event to
  669.             lea     gb_pp1(gbl),a0          ; setup for release 2.0 just in case
  670.             move.l  a0,gb_ppos1+ie_EventAddress(gbl)
  671.             lea     gb_ppos1(gbl),a0        ; new event to be inserted
  672.             jsr     Insert_PointerPos_Event   
  673.             move.l  #req_onsprite,d0        ; setup to restore pointer
  674.             bra     cre027                  ; get out
  675.  
  676. cre055      move.b  gb_RightKey(gbl),d0
  677.             cmp.w   ie_Code(a3),d0          ; Move Right ?
  678.             bne     cre060                  ; no, branch
  679.             move.w  #s_adjacent_right,d1    ; 1st selection choice
  680.             move.w  #s_right,d2             ; 2nd selection choice
  681.             move.w  #s_leftmost,d3          ; 3rd selection choice
  682.             bra     cre065
  683. cre060      move.b  gb_LeftKey(gbl),d0
  684.             cmp.w   ie_Code(a3),d0          ; Move Left ?
  685.             bne     cre125                  ; no, branch
  686.             move.w  #s_adjacent_left,d1     ; 1st selection choice
  687.             move.w  #s_left,d2              ; 2nd selection choice
  688.             move.w  #s_rightmost,d3         ; 3rd selection choice
  689. cre065      move.b  ie_Qualifier+1(a3),d0   ; get key qualifier
  690.             and.b   gb_Qual(gbl),d0         ; was qualifier key present ?
  691.             beq     cre067                  ; no,branch
  692. *-----------------------------------------------------------------------------*
  693. *           The menu 'right' or 'left' key was pressed. See if a qualifier    *
  694. *           key was also present. If so, we move to either rightmost or       *
  695. *           leftmost menu.                                                    *
  696. *-----------------------------------------------------------------------------*
  697.             move.w  #s_rightmost,d0         ; select rightmost
  698.             cmp.w   d0,d3                   ; same selection ?
  699.             bne     cre107                  ; no, branch
  700.             move.w  #s_leftmost,d0          ; select leftmost
  701.             bra     cre107                  ; go choose the menu
  702. *-----------------------------------------------------------------------------*
  703. *           The menu 'right' or 'left' key was pressed. Now we must see if    *
  704. *           a subitem list exists for the current menu item.                  *
  705. *-----------------------------------------------------------------------------*
  706. cre067      move.l  gb_currentitem(gbl),a0  ; get current menu item ptr
  707.             move.l  mi_SubItem(a0),a1       ; get its menu subitem ptr, if any
  708.             move.l  a1,d0                   ; set cc
  709.             beq     cre100                  ; no subitems on this menu, branch
  710. *-----------------------------------------------------------------------------*
  711. *           There are subitems attached to this menu item. Some explanation   *
  712. *           is in order here. With Intuition, menu subitems can be rendered   *
  713. *           anywhere on the menu display as long as at least one pixel of the *
  714. *           menu subitem overlaps a pixel of its associated menu item.        *
  715. *           Generally, subitems are designed to appear either to the right of *
  716. *           its associated menu item or to the left. This affects our         *
  717. *           interpretation of what the user wants to do when they press       *
  718. *           either the menu right or menu left key.  For example, if the menu *
  719. *           subitems are positioned to the right of the menu item and the     *
  720. *           menu right key is pressed, this means that the user intends to    *
  721. *           step into the menu subitem list. If the menu subitems are         *
  722. *           positioned on the left and the menu right key is pressed, the     *
  723. *           user wants to step to the next list of menu items on the right    *
  724. *           (or wrap to the first set of menu items if we are positioned on   *
  725. *           the rightmost menu item). Here we check the leftedge of the       * 
  726. *           subitem to see if it is greater than zero to determine if the     *
  727. *           subitem's leftedge is to the left of the menu item's leftedge.    *
  728. *           The result of this comparison is saved in d4 and is used later    *
  729. *           in determining what the user's intentions are.                    *
  730. *-----------------------------------------------------------------------------*
  731.             clr.w   d0
  732.             cmp.w   mi_LeftEdge(a1),d0      ; check subitem's leftedge
  733.             sgt     d4                      ; save comparison result
  734.             tst.l   gb_currentsubitem(gbl)  ; are we processing subitems ?
  735.             bne     cre080                  ; yes, branch
  736. *-----------------------------------------------------------------------------*
  737. *           We are positioned on a menu item that has subitems attached and   *
  738. *           the user has pressed the menu right or menu left key. Determine   *
  739. *           what their intention is. Either they want to step into the        *
  740. *           subitem list or they want to select the next menu item.           *
  741. *-----------------------------------------------------------------------------*
  742.             clr.l   d0
  743.             move.b  gb_RightKey(gbl),d0     ; setup for compare
  744.             cmp.w   ie_Code(a3),d0          ; right key ?
  745.             bne     cre070                  ; no, branch
  746.             tst.b   d4                      ; are subitems on menu items left ?
  747.             beq     cre075                  ; no, step into the subitem list
  748.             bra     cre100                  ; yes, step to next menu item list
  749. cre070      tst.b   d4                      ; are subitems on menu items left ?
  750.             beq     cre100                  ; no, step to next menu item list
  751.                                             ; yes, step into the subitem list
  752. *-----------------------------------------------------------------------------*
  753. *           The user wants to step into the subitem list. Select the topmost  *
  754. *           adjacent subitem in the list. (Note: there can be subitems        *
  755. *           positioned horizontally as well as vertically)                    * 
  756. *-----------------------------------------------------------------------------*
  757. cre075      move.w  #s_adjacent_top,d0      ; set to select the topmost subitem
  758.             move.l  a1,a0                   ; list of subitems to choose from
  759.             jsr     Select_Item             ; go find the subitem
  760.             move.l  d0,gb_currentsubitem(gbl) ; save it in our globals
  761.             bra     cre085                  ; go generate an event
  762. *-----------------------------------------------------------------------------*
  763. *           We are currently positioned on a menu subitem and the user has    *
  764. *           pressed either the menu right key or menu left key. Determine     *
  765. *           what their intention is. If there is another subitem positioned   *
  766. *           adjacent to the current subitem in the direction of the key that  *
  767. *           was pressed, that subitem will be selected. Otherwise, the user   *
  768. *           wants to step out of the subitem list.                            *
  769. *-----------------------------------------------------------------------------*
  770. cre080      move.l  d1,d0                   ; get 1st selection choice
  771.             move.l  a1,a0                   ; list of subitems to choose from
  772.             move.l  gb_currentsubitem(gbl),a1 ; supply current subitem
  773.             jsr     Select_Item             ; go select next subitem
  774.             cmp.l   d0,a1                   ; same item selected ?
  775.             beq     cre090                  ; yes, get out of the subitem list
  776.             move.l  d0,gb_currentsubitem(gbl) ; no, save new subitem
  777. cre085      moveq.l #1,d0                   ; set to build only one event
  778.             bra     cre175                  ; go generate an event
  779. *-----------------------------------------------------------------------------*
  780. *           The user wants to step out of the subitem list. Determine whether *
  781. *           they want to go back to the menu item associated with the subitem *
  782. *           list or to the next menu item.                                    *
  783. *-----------------------------------------------------------------------------*
  784. cre090      clr.l   gb_currentsubitem(gbl)  ; clear current subitem pointer
  785.             clr.l   d0
  786.             move.b  gb_RightKey(gbl),d0     ; setup for compare
  787.             cmp.w   ie_Code(a3),d0          ; right key ?
  788.             bne     cre095                  ; no, branch
  789.             tst.b   d4                      ; are subitems on menu items left ?
  790.             bne     cre085                  ; yes, go back to subitems menu item
  791.             bra     cre100                  ; no, go select next menu item list
  792. cre095      tst.b   d4                      ; are subitems on menu items left ?
  793.             beq     cre085                  ; no, go back to subitems menu item
  794. *-----------------------------------------------------------------------------*
  795. *           Select a menu item. (Note: there can be menu items positioned     *
  796. *           horizontally as well as vertically)                               *
  797. *-----------------------------------------------------------------------------*
  798. cre100      move.l  d1,d0                   ; get 1st selection choice
  799.             move.l  gb_currentmenu(gbl),a0  ; get current menu
  800.             move.l  mu_FirstItem(a0),a0     ; list of items to choose from
  801.             move.l  gb_currentitem(gbl),a1  ; get current menu item
  802.             jsr     Select_Item             ; go select an item
  803.             cmp.l   d0,a1                   ; same item selected ?
  804.             bne     cre115                  ; no, use the new item, branch
  805. *-----------------------------------------------------------------------------*
  806. *           There are no menu items positioned in the horizontal direction of *
  807. *           the key that was pressed, so we must step to the next menu.       *
  808. *-----------------------------------------------------------------------------*
  809.             move.l  d2,d0                   ; get 2nd selection choice
  810.             move.l  gb_menu(gbl),a0         ; list of menus to choose from
  811.             move.l  gb_currentmenu(gbl),a1  ; get current menu
  812.             jsr     Select_Item             ; go select a menu
  813.             cmp.l   d0,a1                   ; same menu selected ?
  814.             beq     cre105                  ; yes, branch
  815.             move.l  d0,gb_currentmenu(gbl)  ; no, use the new menu
  816.             bra     cre110                  ; go select an item in the menu
  817. *-----------------------------------------------------------------------------*
  818. *           There are no menus in the horizontal direction of the key that    *
  819. *           was pressed. We will interpret this to mean that the user wants   *
  820. *           to wrap to the opposite end of the menu strip. For example, if we *
  821. *           are currently on the rightmost menu and the user presses the menu *
  822. *           right key, we will wrap around to the leftmost menu.              *
  823. *-----------------------------------------------------------------------------*
  824. cre105      move.l  d3,d0                   ; set 3rd selection choice
  825. cre107      move.l  gb_menu(gbl),a0         ; list of menus to choose from
  826.             jsr     Select_Item             ; go select again
  827.             move.l  d0,gb_currentmenu(gbl)  ; save new menu
  828. cre110      move.w  #s_top,d0               ; set to select topmost menu item
  829.             move.l  gb_currentmenu(gbl),a0  ; get current menu
  830.             move.l  mu_FirstItem(a0),a0     ; list of items to choose from
  831.             jsr     Select_Item             ; go select a menu item
  832.             move.l  d0,gb_currentitem(gbl)  ; save new item
  833. *-----------------------------------------------------------------------------*
  834. *           Normally, we will generate only one event. A pointerpos event to  *
  835. *           position the pointer on the desired menu item or subitem. Here we *
  836. *           have determined that a new menu is to be selected. This requires  *
  837. *           us to generate 2 events. The first will be a pointerpos event to  *
  838. *           position the pointer in the menu strip over the menu that we want *
  839. *           to select. This causes Intuition to remove the rendering of the   *
  840. *           current menu from the display and render the menu that we are     *
  841. *           selecting. The second event will be a pointerpos event to         *
  842. *           position the pointer on the menu item that we have chosen.        *
  843. *-----------------------------------------------------------------------------*
  844.             moveq.l #2,d0                   ; set number of events to build
  845.             bra     cre120
  846. cre115      move.l  d0,gb_currentitem(gbl)  ; save new item
  847.             moveq.l #1,d0                   ; set number of events to build
  848. cre120      clr.l   gb_currentsubitem(gbl)  ; clear current subitem pointer
  849.             bra     cre175                  ; go generate event(s)
  850.  
  851. cre125      move.b  gb_DownKey(gbl),d0      ; setup for compare
  852.             cmp.w   ie_Code(a3),d0          ; Down key ?
  853.             bne     cre130                  ; no, branch
  854.             move.w  #s_adjacent_up,d1       ; 1st selection choice
  855.             move.w  #s_up,d2                ; 2nd selection choice
  856.             move.w  #s_top,d3               ; 3rd selection choice
  857.             bra     cre135                  ; go handle keypress
  858. cre130      move.b  gb_UpKey(gbl),d0        ; setup for compare
  859.             cmp.w   ie_Code(a3),d0          ; Up key ?
  860.             bne     cre_keep                ; no, pass this event on
  861.             move.w  #s_adjacent_down,d1     ; 1st selection choice
  862.             move.w  #s_down,d2              ; 2nd selection choice
  863.             move.w  #s_bottom,d3            ; 3rd selection choice
  864. *-----------------------------------------------------------------------------*
  865. *           The menu 'up' or 'down' key was pressed. If we are currently      *
  866. *           positioned in a subitem menu, setup to select the appropriate     *
  867. *           subitem otherwise setup to select the appropriate menu item.      *
  868. *-----------------------------------------------------------------------------*
  869. cre135      moveq.l #1,d4                   ; set default # events to be created
  870.             tst.l   gb_currentsubitem(gbl)  ; are we processing subitems ?
  871.             beq     cre140                  ; no, branch
  872.             move.l  gb_currentsubitem(gbl),a1 ; supply parameters to process
  873.             move.l  gb_currentitem(gbl),a0    ; menu subitems
  874.             move.l  mi_SubItem(a0),a0
  875.             bra     cre145
  876. cre140      move.l  gb_currentitem(gbl),a1  ; supply parameters to process menu
  877.             move.l  gb_currentmenu(gbl),a0  ; items
  878.             move.l  mu_FirstItem(a0),a0
  879. *-----------------------------------------------------------------------------*
  880. *           Here we check to see if there are subitems attached to the        *
  881. *           current menu item. If so, we will generate 2 events. The first    *
  882. *           will be a pointerpos event to position the pointer on the menu    *
  883. *           strip. The second will be a pointerpos event to position the      *
  884. *           pointer on the desired menu item. This is done to cause Intuition *
  885. *           to remove the subitem's rendering from the display in case it     *
  886. *           overlaps onto the menu item being selected. Without this, we      *
  887. *           would tell Intuition to position the mouse on the new menu item   *
  888. *           but the overlapping subitems from the current menu item would     *
  889. *           still be displayed causing us to select a menu subitem instead of *
  890. *           the menu item that we intended to select.                         *
  891. *-----------------------------------------------------------------------------*
  892.             tst.l   mi_SubItem(a1)          ; are there subitems attached to
  893.                                             ; this menu item ?
  894.             beq     cre145                  ; no, branch
  895.             moveq.l #2,d4                   ; yes, use 2 events to select item
  896. cre145      move.b  ie_Qualifier+1(a3),d0   ; get key qualifier
  897.             and.b   gb_Qual(gbl),d0         ; was qualifier key present ?
  898.             beq     cre147                  ; no, branch
  899. *-----------------------------------------------------------------------------*
  900. *           See if a qualifier key was also present. If so, we move to either *
  901. *           topmost or bottommost menu or submenu item.                       *
  902. *-----------------------------------------------------------------------------*
  903.             move.w  #s_bottom,d0            ; select bottom
  904.             cmp.w   d0,d3                   ; same selection ?
  905.             bne     cre153                  ; no, branch
  906.             move.w  #s_top,d0               ; select top
  907.             bra     cre153
  908. cre147      move.l  d1,d0                   ; get 1st selection choice
  909.             jsr     Select_Item             ; go select a menuitem or subitem
  910.             cmp.l   d0,a1                   ; same item selected ?
  911.             bne     cre155                  ; no, use the new one
  912.             move.l  d2,d0                   ; get 2nd selection choice
  913.             jsr     Select_Item             ; select again
  914. cre150      cmp.l   d0,a1                   ; same item selected ?
  915.             bne     cre155                  ; no, use new item
  916.             move.l  d3,d0                   ; get 3rd selection choice
  917. cre153      jsr     Select_Item             ; go select again
  918. cre155      move.l  d0,a1                   ; save new item
  919. cre160      tst.l   gb_currentsubitem(gbl)  ; are we processing subitems ?
  920.             beq     cre165                  ; no, branch
  921.             move.l  a1,gb_currentsubitem(gbl) ; yes, save new subitem
  922.             bra     cre170
  923. cre165      move.l  a1,gb_currentitem(gbl)  ; save new item
  924. cre170      move.l  d4,d0                   ; get # of events to be generated
  925. cre175      jsr     dobuild                 ; go build our events
  926. *-----------------------------------------------------------------------------*
  927. *           Indicate that the original input event passed to this routine is  *
  928. *           to be removed from the input event chain and return.              *
  929. *-----------------------------------------------------------------------------*
  930. cre_remove  moveq.l #1,d0                   ; indicate old event to be removed
  931.             bra     cre_exit                ; go to common return
  932. *-----------------------------------------------------------------------------*
  933. *           Indicate that the original input event passed to this routine is  *
  934. *           to be kept in the input event chain and return.                   *
  935. *-----------------------------------------------------------------------------*
  936. cre_keep    clr.l   d0                      ; indicate old event to be kept
  937. cre_exit    movem.l (sp)+,creregs           ; restore registers
  938.             rts                             ; return to caller
  939. creregs     reg     a1-a3/a5/d2-d4
  940.  
  941. *******************************************************************************
  942. *                                                                             * 
  943. *       dobuild                                                               *
  944. *                                                                             *
  945. *       This routine is called by Check_RawKey_Event to perform a general     *
  946. *       call to the Build_PointerPos_Event routine.                           *
  947. *                                                                             *
  948. *       Input Registers:                                                      *
  949. *           a3 - input event to attach new events to                          *
  950. *           a4 - global work area                                             *
  951. *                                                                             *
  952. *       Output Registers:                                                     *
  953. *           a0 - new input event                                              *
  954. *           a1 - original input event                                         *
  955. *                                                                             *
  956. *******************************************************************************
  957. dobuild     move.l  a3,a1                   ; pass original input event
  958. db010       lea     gb_pp2(gbl),a0          ; setup for release 2 just in case
  959.             move.l  a0,gb_ppos2+ie_EventAddress(gbl)
  960.             lea     gb_ppos2(gbl),a0        ; point to our input event area
  961.             jsr     Build_PointerPos_Event  ; go create our input events
  962.             rts                             ; return to caller
  963.  
  964. *******************************************************************************
  965. *                                                                             * 
  966. *       Verify_Item                                                           *
  967. *                                                                             *
  968. *       This routine is called by Check_RawKey_Event to verify if a menu or   *
  969. *       menu item is a member of a provided list of menu/menu items.          *
  970. *                                                                             *
  971. *       Input Registers:                                                      *
  972. *           a0 - menu/menu item list                                          *
  973. *           a1 - item to be verified.                                         *
  974. *                                                                             *
  975. *       Output Registers:                                                     *
  976. *           d0 - 0=no match, 1=match                                          *
  977. *                                                                             *
  978. *******************************************************************************
  979. Verify_Item movem.l viregs,-(sp)
  980. vi010       cmp.l   a0,a1                   ; does this item match ?
  981.             beq     vi015                   ; yes, branch
  982.             move.l  im_NextItem(a0),d0      ; get next item's address
  983.             beq     vi020                   ; entire list scanned, branch
  984.             move.l  d0,a0                   ; use next item's address
  985.             bra     vi010                   ; loop to check next item
  986. vi015       moveq.l #1,d0                   ; indicate that the item exists
  987. vi020       movem.l (sp)+,viregs
  988.             rts
  989. viregs      reg     a0/a1
  990.  
  991. *******************************************************************************
  992. *                                                                             * 
  993. *       Select_Item                                                           *
  994. *                                                                             *
  995. *       This routine is called to select a menu, menu item or menu subitem.   *
  996. *       Given a list of items to choose from, the attribute of the item       *
  997. *       desired and the current item; this routine attempts to find a new     *
  998. *       item that matches the desired attribute. For example, if d0 contains  *
  999. *       's_up' the list of items provided is scanned to find the closest item *
  1000. *       that is physically above the current item on the display.             *
  1001. *                                                                             *
  1002. *       Input Registers:                                                      *
  1003. *           a0 - menu/menu item/menu subitem list                             *
  1004. *           a1 - current item                                                 *
  1005. *           d0 - type of item desired in relation to current item             *
  1006. *                                                                             *
  1007. *       Output Registers:                                                     *
  1008. *           d0 - selected item (or current item if no item was selected)      *
  1009. *                                                                             *
  1010. *******************************************************************************
  1011. Select_Item
  1012.  
  1013. select_type equr    d0                      ; select type & return value
  1014. item        equr    a0                      ; item list
  1015. currentitem equr    a1                      ; currentitem
  1016. returnitem  equr    a2                      ; return item
  1017. work        equr    d1                      ; work register
  1018.  
  1019. *-----------------------------------------------------------------------------*
  1020. *           'returnitem' contains the address of the item that is being       *
  1021. *           considered for return to the calling routine. Here we create a    *
  1022. *           dummy item on the stack that contains extreme values for topedge  *
  1023. *           and leftedge. The address of this entry is loaded into            *
  1024. *           'returnitem' to give us an initial entry to compare against.      *
  1025. *           For example, if 's_leftmost' is the attribute of the item that we *
  1026. *           are searching for, the leftedge field in the dummy entry would    *
  1027. *           contain 32768. In an effort to find the 'leftmost' item in the    *
  1028. *           list, the 'si_leftmost' portion of this routine will compare the  *
  1029. *           leftedge of each item in the list with the leftedge of            *
  1030. *           'returnitem'. When an item is found with a leftedge that is less  *
  1031. *           than returnitem's, its address is placed in returnitem. When the  *
  1032. *           end of the list is reached, the item with the lowest leftedge     *
  1033. *           should be contained in 'returnitem'                               *
  1034. *-----------------------------------------------------------------------------*
  1035.             link    a5,#-im_size
  1036.             movem.l siregs,-(sp)
  1037.             move.w  #32767,work
  1038.             cmp.w   #s_leftmost,select_type
  1039.             ble     si010
  1040.             move.w  #-32768,work
  1041. si010       lea     -im_size(a5),returnitem          
  1042.             move.w  work,im_TopEdge(returnitem) ; setup dummy item
  1043.             move.w  work,im_LeftEdge(returnitem)
  1044.             bra     si_jmp                  ; go to computed jump
  1045. si_adjacent_up
  1046.             move.w  im_LeftEdge(item),work
  1047.             cmp.w   im_LeftEdge(currentitem),work
  1048.             bne     si_check_end
  1049. si_up       move.w  im_TopEdge(item),work
  1050.             cmp.w   im_TopEdge(currentitem),work
  1051.             ble     si_check_end
  1052. si_top
  1053. si_adjacent_top
  1054.             move.w  im_TopEdge(item),work
  1055.             cmp.w   im_TopEdge(returnitem),work
  1056.             bge     si015
  1057.             move.l  item,returnitem
  1058. si015       cmp.w   #s_adjacent_top,select_type
  1059.             bne     si_check_end
  1060.             move.w  im_TopEdge(item),work
  1061.             cmp.w   im_TopEdge(returnitem),work
  1062.             bne     si_check_end
  1063.             move.w  im_LeftEdge(item),work
  1064.             cmp.w   im_LeftEdge(returnitem),work
  1065.             bge     si_check_end
  1066.             move.l  item,returnitem
  1067.             bra     si_check_end
  1068. si_adjacent_right
  1069.             move.w  im_TopEdge(item),work
  1070.             cmp.w   im_TopEdge(currentitem),work
  1071.             bne     si_check_end
  1072. si_right    move.w  im_LeftEdge(item),work
  1073.             cmp.w   im_LeftEdge(currentitem),work
  1074.             ble     si_check_end
  1075. si_leftmost move.w  im_LeftEdge(item),work
  1076.             cmp.w   im_LeftEdge(returnitem),work
  1077.             bge     si_check_end
  1078.             move.l  item,returnitem
  1079.             bra     si_check_end
  1080. si_adjacent_down
  1081.             move.w  im_LeftEdge(item),work
  1082.             cmp.w   im_LeftEdge(currentitem),work
  1083.             bne     si_check_end
  1084. si_down     move.w  im_TopEdge(item),work
  1085.             cmp.w   im_TopEdge(currentitem),work
  1086.             bge     si_check_end
  1087. si_bottom   move.w  im_TopEdge(item),work
  1088.             cmp.w   im_TopEdge(returnitem),work
  1089.             ble     si_check_end
  1090.             move.l  item,returnitem
  1091.             bra     si_check_end
  1092. si_adjacent_left
  1093.             move.w  im_TopEdge(item),work
  1094.             cmp.w   im_TopEdge(currentitem),work
  1095.             bne     si_check_end
  1096. si_left     move.w  im_LeftEdge(item),work
  1097.             cmp.w   im_LeftEdge(currentitem),work
  1098.             bge     si_check_end
  1099. si_rightmost
  1100.             move.w  im_LeftEdge(item),work
  1101.             cmp.w   im_LeftEdge(returnitem),work
  1102.             ble     si_check_end
  1103.             move.l  item,returnitem
  1104. si_check_end
  1105.             move.l  im_NextItem(item),item
  1106.             move.l  item,work               ; set cc
  1107.             beq     si_end
  1108. si_jmp      jmp     (pc,d0.w)               ; jump to proper routine
  1109. si_end      lea     -im_size(a5),item
  1110.             cmp.l   item,returnitem         ; still pointing to dummy item ?
  1111.             bne     si_return               ; no, branch
  1112.             move.l  currentitem,returnitem  ; yes, pass currentitem back
  1113. si_return   move.l  returnitem,d0           ; set return 
  1114.             movem.l (sp)+,siregs            ; restore regs
  1115.             unlk    a5                      ; remove area from stack
  1116.             rts                             ; return to caller
  1117. siregs      reg     d1/a0-a2
  1118.  
  1119. *******************************************************************************
  1120. *                                                                             * 
  1121. *       Insert_PointerPos_Event                                               *
  1122. *                                                                             *
  1123. *       This routine creates a pointerpos event and attaches it to the input  *
  1124. *       event provided.                                                       *
  1125. *                                                                             *
  1126. *       Input Registers:                                                      *
  1127. *           a0 - new event to be inserted                                     *
  1128. *           a1 - input event to attach new event to                           *
  1129. *           d0 - Mouse X coordinate to place in new event                     *
  1130. *           d1 - Mouse Y coordinate to place in new event                     *
  1131. *                                                                             *
  1132. *       Output Registers:                                                     *
  1133. *           none.                                                             *
  1134. *                                                                             *
  1135. *******************************************************************************
  1136. Insert_PointerPos_Event
  1137.             btst.b  #FLAGB_Release2,gb_flags2(gbl)   ; release 2.0 ?
  1138.             bne     ipe010                           ; yes, branch
  1139.             move.b  #IECLASS_POINTERPOS,ie_Class(a0) ; build mousemove event
  1140.             move.w  #IECODE_NOBUTTON,ie_Code(a0)
  1141.             move.w  d0,ie_X(a0)             ; set coordinates
  1142.             move.w  d1,ie_Y(a0)
  1143.             bra     ire010
  1144. ipe010      move.b  #IECLASS_NEWPOINTERPOS,ie_Class(a0)
  1145.             move.b  #IESUBCLASS_PIXEL,ie_SubClass(a0)
  1146.             clr.w   ie_Code(a0)
  1147.             clr.w   ie_Qualifier(a0)
  1148.             move.l  ie_NextEvent(a1),ie_NextEvent(a0) ; chain to original event
  1149.             move.l  a0,ie_NextEvent(a1)
  1150.             move.l  ie_EventAddress(a0),a0
  1151.             move.l  gb_window(gbl),a1                 ; get current window
  1152.             move.l  wd_WScreen(a1),iepp_Screen(a0)    ; supply screen
  1153.             move.w  d0,iepp_PositionX(a0)             ; supply pointer 
  1154.             move.w  d1,iepp_PositionY(a0)             ;   coordinates
  1155.             rts
  1156.       
  1157. *******************************************************************************
  1158. *                                                                             * 
  1159. *       Insert_RawMouse_Event                                                 *
  1160. *                                                                             *
  1161. *       This routine creates a rawmouse event and attaches it to the input    *
  1162. *       event provided.                                                       *
  1163. *                                                                             *
  1164. *       Input Registers:                                                      *
  1165. *           a1 - input event to attach new event to                           *
  1166. *           d0 - type of rawmouse event                                       *
  1167. *                                                                             *
  1168. *       Output Registers:                                                     *
  1169. *           none.                                                             *
  1170. *                                                                             *
  1171. *******************************************************************************
  1172. Insert_RawMouse_Event
  1173.             lea     gb_rawm(gbl),a0
  1174.             move.b  #IECLASS_RAWMOUSE,ie_Class(a0) ; build rawmouse event
  1175.             move.w  d0,ie_Code(a0)
  1176.             clr.w   ie_X(a0)
  1177.             clr.w   ie_Y(a0)
  1178. ire010      clr.b   ie_SubClass(a0)
  1179.             clr.w   ie_Qualifier(a0)
  1180.             move.l  ie_NextEvent(a1),ie_NextEvent(a0) ; chain to original event
  1181.             move.l  a0,ie_NextEvent(a1)
  1182.             rts                             ; return to caller
  1183.  
  1184. *******************************************************************************
  1185. *                                                                             * 
  1186. *       Build_PointerPos_Event                                                *
  1187. *                                                                             *
  1188. *       This routine creates pointer position event(s) and attaches them to   *
  1189. *       the input event provided. The resolution of the current screen is     *
  1190. *       taken into account when generating the events. The coordinates of the *
  1191. *       pointer position events are alway represented in the highest          *
  1192. *       resolution i.e. 640x400. The coordinate fields of menus, menu items,  *
  1193. *       etc. are represented in the resolution of the screen to which the     *
  1194. *       menu is attached. When we position the pointer on anything but a      *
  1195. *       hires interlace screen, we must adjust the coordinates that are taken *
  1196. *       from the menus to allow for this.                                     *
  1197. *                                                                             *
  1198. *       Input Registers:                                                      *
  1199. *           a0 - address of input event to be built                           *
  1200. *           a1 - original input event                                         *
  1201. *           d0 - number of input events to generate.                          *
  1202. *                                                                             *
  1203. *       Output Registers:                                                     *
  1204. *           none.                                                             *
  1205. *                                                                             *
  1206. *******************************************************************************
  1207. Build_PointerPos_Event
  1208.  
  1209. iheight     equr    d1
  1210. iwidth      equr    d1
  1211. itopedge    equr    d2
  1212. ileftedge   equr    d2
  1213. mheight     equr    d3
  1214. mwidth      equr    d3
  1215. mtopedge    equr    d4
  1216. mleftedge   equr    d4
  1217. offsetx     equr    d5
  1218. offsety     equr    d6
  1219.  
  1220.             movem.l bperegs,-(sp)           ; save registers
  1221.             jsr     Insert_PointerPos_Event ; go insert new event
  1222.             move.l  gb_window(gbl),a2       ; get current window
  1223.             move.l  wd_WScreen(a2),a2       ; get window's screen
  1224.             move.l  gb_currentmenu(gbl),a3  ; get current menu
  1225.             clr.w   mtopedge                ; force menu's topedge to zero
  1226.             btst.b  #FLAGB_Release2,gb_flags2(gbl) ; release 2.0 ?
  1227.             bne     bpe003                         ; yes, branch
  1228.             add.w   sc_ViewPort+vp_DyOffset(a2),mtopedge ; add screen's offset
  1229. bpe003      swap    mtopedge
  1230.             move.w  mu_LeftEdge(a3),mleftedge ; get menu's leftedge
  1231.             btst.b  #FLAGB_Release2,gb_flags2(gbl) ; release 2.0 ?
  1232.             bne     bpe006                         ; yes, branch
  1233.             add.w   sc_ViewPort+vp_DxOffset(a2),mleftedge ; add screen's offset
  1234. bpe006      clr.l   mheight
  1235.             move.b  sc_BarHeight(a2),mheight ; get menu's height
  1236.             swap    mheight
  1237.             move.w  mu_Width(a3),mwidth     ; get menu's width
  1238.             move.l  gb_currentitem(gbl),a3  ; get current menuitem
  1239.             move.w  mi_TopEdge(a3),itopedge ; get menuitem's topedge
  1240.             swap    itopedge
  1241.             move.w  mi_LeftEdge(a3),ileftedge ; get menuitem's leftedge
  1242.             move.w  mi_Height(a3),iheight   ; get menuitem's height
  1243.             swap    iheight
  1244.             move.w  mi_Width(a3),iwidth     ; get menuitem's width
  1245.             move.l  gb_currentsubitem(gbl),a5 ; is there a subitem ?
  1246.             move.l  a5,d5                   ; set cc
  1247.             beq     bpe010                  ; no, branch
  1248.             add.w   mi_LeftEdge(a5),ileftedge ; yes, add subitem's leftedge
  1249.             move.w  mi_Width(a5),iwidth     ; use subitem's width
  1250.             swap    ileftedge
  1251.             add.w   mi_TopEdge(a5),itopedge ; add subitem's topedge
  1252.             swap    itopedge
  1253.             swap    iwidth
  1254.             move.w  mi_Height(a5),iheight   ; use subitem's height
  1255.             swap    iheight
  1256.             bra     bpe025
  1257. bpe010      move.l  mi_SubItem(a3),a5       ; is there a subitem for this item ?
  1258.             move.l  a5,d5                   ; set cc
  1259.             beq     bpe025                  ; no, branch
  1260.             movem.l d0/a0,-(sp)             ; save our registers
  1261.             move.l  a5,a0                   ; setup subitem for Select_Item
  1262.             clr.w   d5
  1263.             cmp.w   mi_LeftEdge(a5),d5      ; is subitem rendered on item's left ?
  1264.             ble     bpe020                  ; no, branch
  1265.             move.l  #s_rightmost,d0         ; set select type
  1266.             jsr     Select_Item
  1267.             move.l  d0,a5                   ; get selected item
  1268.             move.w  mi_LeftEdge(a5),d0
  1269.             add.w   mi_Width(a5),d0
  1270.             add.w   d0,ileftedge            ; adjust item's leftedge & width
  1271.             sub.w   d0,iwidth
  1272.             bra     bpe023
  1273. bpe020      move.l  #s_adjacent_top,d0      ; set select type
  1274.             jsr     Select_Item
  1275.             move.l  d0,a5                   ; get selected item
  1276.             move.w  mi_LeftEdge(a5),iwidth
  1277.             sub.w   #1,iwidth
  1278. bpe023      movem.l (sp)+,d0/a0             ; restore our registers
  1279. bpe025      btst.b  #FLAGB_Release2,gb_flags2(gbl) ; Release 2.0 ?
  1280.             beq     bpe027                         ; no, branch
  1281.             sub.l   #ie_X-iepp_PositionX,a0        ; adjust coordinates address
  1282.             bra     bpe035
  1283. bpe027      move.w  sc_ViewPort+vp_Modes(a2),d5 ; get screen modes
  1284.             btst.l  #V_HIRES_B,d5           ; is this a hires screen ?
  1285.             bne     bpe030                  ; yes, branch
  1286.             asl.w   #1,iwidth               ; no, adjust coordinates for hires
  1287.             asl.w   #1,ileftedge
  1288.             asl.w   #1,mwidth
  1289.             asl.w   #1,mleftedge
  1290. bpe030      btst.l  #V_LACE_B,d5            ; is this an interlace screen ?
  1291.             bne     bpe035                  ; yes, branch
  1292.             swap    iwidth                  ; no, adjust coordinates for interlace
  1293.             swap    ileftedge
  1294.             swap    mwidth
  1295.             swap    mleftedge
  1296.             asl.w   #1,iheight
  1297.             asl.w   #1,itopedge
  1298.             asl.w   #1,mheight
  1299.             asl.w   #1,mtopedge
  1300.             swap    iheight
  1301.             swap    itopedge
  1302.             swap    mheight
  1303.             swap    mtopedge
  1304. bpe035      move.l  gb_IBase(gbl),a5        ; get intuition base
  1305.             addq.w  #1,mleftedge
  1306.             move.w  mleftedge,offsetx       ; get menu leftedge
  1307.             move.w  offsetx,ie_X(a0)        ; update event's X coordinate
  1308.             swap    mleftedge
  1309.             addq.w  #1,mtopedge
  1310.             move.w  mtopedge,offsety        ; get menu topedge
  1311.             move.w  offsety,ie_Y(a0)        ; update event's Y coordinate
  1312.             asr.w   #1,mwidth               ; divide menu width by 2
  1313.             move.w  ileftedge,offsetx       ; get item leftedge
  1314.             asr.w   #1,iwidth               ; divide item width by 2
  1315.             add.w   iwidth,offsetx          ; add it to offsetx
  1316.             swap    mwidth
  1317.             move.w  mheight,offsety         ; get menu height
  1318.             asr.w   #1,mheight              ; divide menu height by 2
  1319.             swap    mheight
  1320.             swap    ileftedge
  1321.             add.w   itopedge,offsety        ; add item topedge
  1322.             swap    iwidth
  1323.             asr     #1,iheight              ; divide item height by 2
  1324.             add.w   iheight,offsety         ; add to offsety
  1325.             cmp.w   #1,d0                   ; one event to be generated ?
  1326.             bne     bpe040                  ; no, branch
  1327.             add.w   offsetx,ie_X(a0)        ; adjust mouse x coordinate
  1328.             add.w   offsety,ie_Y(a0)        ; adjust mouse y coordinate
  1329.             bra     bpe045
  1330. bpe040      cmp.w   #3,d0                   ; go to saved mouse position ?
  1331.             bne     bpe042                  ; no, branch
  1332.             move.w  gb_old_MouseX(gbl),offsetx
  1333.             move.w  gb_old_MouseY(gbl),offsety
  1334.             bra     bpe044
  1335. bpe042      add.w   ie_X(a0),offsetx
  1336.             add.w   ie_Y(a0),offsety
  1337. bpe044      add.w   mwidth,ie_X(a0)         ; add menu width to current item
  1338.             swap    mwidth
  1339.             add.w   mheight,ie_Y(a0)        ; add menu height to current item
  1340.             lea     gb_ppos2(gbl),a1
  1341.             lea     gb_pp1(gbl),a0          ; setup for release 2.0 just in case
  1342.             move.l  a0,gb_ppos1+ie_EventAddress(gbl)
  1343.             lea     gb_ppos1(gbl),a0        ; new event area
  1344.             move.w  offsetx,d0
  1345.             move.w  offsety,d1
  1346.             jsr     Insert_PointerPos_Event ; go add the event to the chain
  1347. bpe045      bset.b  #FLAGB_Events_inserted,gb_flags(gbl) ; indicate events added
  1348.             movem.l (sp)+,bperegs
  1349.             rts                             ; return to caller
  1350. bperegs     reg     a0-a5/d1-d6
  1351.  
  1352.             end
  1353.